package com.rex.saas.controller;

import com.github.benmanes.caffeine.cache.Cache;
import com.rex.saas.bean.BaseResponse;
import com.rex.saas.bean.ResultCode;
import com.rex.saas.bean.SpaceInfo;
import com.rex.saas.bean.UserDetails;
import com.rex.saas.bean.request.*;
import com.rex.saas.constants.Constants;
import com.rex.saas.db.entity.SaasSpaceInfo;
import com.rex.saas.db.entity.SaasUserInfo;
import com.rex.saas.enums.ErrorCodeEnum;
import com.rex.saas.service.AppleIdValidService;
import com.rex.saas.service.SpaceService;
import com.rex.saas.service.UserService;
import com.rex.saas.utils.EmailSender163;
import com.rex.saas.utils.JwtUtils;
import com.rex.saas.utils.PasswordValidator;
import com.rex.saas.utils.StringValidatorUtils;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ThreadLocalRandom;

/**
 * @ClassName UserController
 * @Description:
 * @Author: zhusiyu
 * @CreateDate: 2024/12/18 10:55	//创建时间
 */
@RestController
@Slf4j
public class UserController {

    @Autowired
    private UserService userService;

    @Autowired
    private SpaceService spaceService;

    @Autowired
    AppleIdValidService appleIdValidService;

    @Autowired
    private Cache<String, String> resetTokenCache;

    @Autowired
    private Cache<String, String> registerTokenCache;

    @PostMapping("/modifyPassword")
    public BaseResponse modifyPassword(@RequestBody ModifyPwdRequest modifyPassword) {

        String username = modifyPassword.getUsername();
        String newPassword = modifyPassword.getNewPassword();
        String password = modifyPassword.getPassword();
        if (StringUtils.isEmpty(username) || StringUtils.isEmpty(newPassword) || StringUtils.isEmpty(password)) {
            log.error("username, new password, or password is empty.");
            return BaseResponse.error(ResultCode.PARAM_ERROR);
        }
        if(!PasswordValidator.validatePasswordWithThreeTypes(newPassword)){
            log.error("password format is wrong！ modifyPassword：{}",modifyPassword);
            return BaseResponse.error("password format is wrong！！", ResultCode.PARAM_ERROR);
        }

        SaasUserInfo saasUserInfo = userService.getUserByUsername(username);
        if (saasUserInfo == null) {
            log.error("modifyPassword User is null, username:{}", username);
            return BaseResponse.error(ResultCode.PARAM_ERROR.getStatus(), "username is wrong！");
        }

        if (!password.equals(saasUserInfo.getPassword())) {
            log.error("modifyPassword password is wrong, user:{}", saasUserInfo);
            return BaseResponse.error(ResultCode.PARAM_ERROR.getStatus(), "password is wrong!");
        }

        // 更新用户密码
        boolean flag = userService.updatePassword(saasUserInfo, newPassword);
        if (!flag) {
            log.error("Update user password error, username:{}", username);
            return BaseResponse.error(ResultCode.SYSTEM_ERROR.getStatus(), "更新用户密码失败！");
        }

        return BaseResponse.ok(flag);
    }
    @PostMapping("/resetPassword")
    public BaseResponse resetPassword(@RequestBody ResetPwdRequest resetPwdRequest) {
        log.info("resetPassword resetPwdRequest:{}", resetPwdRequest);
        String email = resetPwdRequest.getEmail();
        String newPassword = resetPwdRequest.getNewPassword();
        String verifyCode = resetPwdRequest.getVerifyCode();
        if (StringUtils.isEmpty(email) || StringUtils.isEmpty(newPassword) || StringUtils.isEmpty(verifyCode)) {
            log.error("Email, new password, or verifyCode is empty.");
            return BaseResponse.error(ResultCode.PARAM_ERROR);
        }
        if(!PasswordValidator.validatePasswordWithThreeTypes(newPassword)){
            log.error("password format is wrong！ resetPwdRequest：{}",resetPwdRequest);
            return BaseResponse.error("password format is wrong！！", ResultCode.PARAM_ERROR);
        }
        // 从缓存中获取令牌
        String cachedToken = resetTokenCache.getIfPresent(email);

        // 验证令牌有效性
        if (cachedToken == null || !cachedToken.equals(verifyCode)) {
            log.error("verifyCode is invalid or expired.");
            return BaseResponse.error("verifyCode is wrong！！", ResultCode.PARAM_ERROR);
        }

        SaasUserInfo saasUserInfo = userService.getUserByUsername(email);
        if (saasUserInfo == null) {
            log.error("User is null, email:{}", email);
            return BaseResponse.error(ResultCode.PARAM_ERROR.getStatus(), "email is wrong！");
        }


        // 更新用户密码
        boolean flag = userService.updatePassword(saasUserInfo, newPassword);
        if (!flag) {
            log.error("Update user password error, email:{}", email);
            return BaseResponse.error(ResultCode.SYSTEM_ERROR.getStatus(), "更新用户密码失败！");
        }

        // 清除缓存中的令牌
        resetTokenCache.invalidate(email);

        return BaseResponse.ok();
    }

    @GetMapping("/resetMail")
    public BaseResponse resetMail(HttpServletRequest request, @RequestParam("email") String email) {
        log.info("resetMail email:{}", email);
        int randomNumber = ThreadLocalRandom.current().nextInt(0, 1000000);
        String verifyCode = String.format("%06d", randomNumber);

        // 将令牌存储到缓存中，key为email
        resetTokenCache.put(email, verifyCode);
        StringBuffer url = request.getRequestURL();
        String domain = url.toString().substring(0, url.toString().lastIndexOf("/"));

        // 构建重置链接
//        String resetLink = domain + "resetPassword?verifyCode=" + verifyCode + "&email=" + email;

        // 发送重置链接到用户邮箱
        try {
            EmailSender163.getInstance().sendEmail(email, "Password Reset Mail",
                    "your Password Reset Verification code : " + verifyCode);
        } catch (Exception e) {
            log.error("Failed to send email.", e);
            return BaseResponse.error(ErrorCodeEnum.SYSTEM_ERROR.getCode(),"Failed to send email.");
        }

        return BaseResponse.ok();
    }

    @RequestMapping("/user/add")
    @ResponseBody
    public BaseResponse add(HttpServletRequest request, @RequestBody UserAddRequest userAddRequest){
        log.info("add userAddRequest:{}", userAddRequest);
        if(StringUtils.isEmpty(userAddRequest.getEmail())){
            return BaseResponse.error("email不能为空！", ResultCode.PARAM_ERROR);
        }
        if(StringUtils.isEmpty(userAddRequest.getPassword())){
            return BaseResponse.error("密码不能为空！", ResultCode.PARAM_ERROR);
        }
        if(StringUtils.isEmpty(userAddRequest.getName())){
            return BaseResponse.error("用户名不能为空！", ResultCode.PARAM_ERROR);
        }
        if(!StringValidatorUtils.isValidEmail(userAddRequest.getEmail())){
            log.error("email format is wrong！ userAddRequest：{}",userAddRequest);
            return BaseResponse.error("email format is wrong！！", ResultCode.PARAM_ERROR);
        }
        if(!PasswordValidator.validatePasswordWithThreeTypes(userAddRequest.getPassword())){
            log.error("password format is wrong！ userAddRequest：{}",userAddRequest);
            return BaseResponse.error("password format is wrong！！", ResultCode.PARAM_ERROR);
        }

        String token = request.getHeader("token");
        List<String> roles = JwtUtils.getRole(token);
        if(!roles.contains(Constants.TENANT_ADMIN)){
            log.error("add , user has not permission");
            return BaseResponse.error("权限不足", ResultCode.PARAM_ERROR);
        }
        return userService.add(userAddRequest, token);
    }

    @RequestMapping("/ctRegister")
    @ResponseBody
    public BaseResponse register(@RequestBody RegisterRequest registerRequest){
        log.info("register:{}", registerRequest);
        if(StringUtils.isEmpty(registerRequest.getEmail())){
            return BaseResponse.error("用户名不能为空！", ResultCode.PARAM_ERROR);
        }
        if(StringUtils.isEmpty(registerRequest.getPassword())){
            return BaseResponse.error("密码不能为空！", ResultCode.PARAM_ERROR);
        }
        if(StringUtils.isEmpty(registerRequest.getVerificationCode())){
            return BaseResponse.error("验证码不能为空！", ResultCode.PARAM_ERROR);
        }
        if(!StringValidatorUtils.isValidEmail(registerRequest.getEmail())){
            log.error("邮箱格式不正确！email:{}", registerRequest.getEmail());
            return BaseResponse.error("邮箱格式不正确！", ResultCode.PARAM_ERROR);
        }
        if(!PasswordValidator.validatePasswordWithThreeTypes(registerRequest.getPassword())){
            log.error("password format is wrong！ registerRequest：{}",registerRequest);
            return BaseResponse.error("password format is wrong！！", ResultCode.PARAM_ERROR);
        }

        String vcode = registerTokenCache.getIfPresent(registerRequest.getEmail());
        if(StringUtils.isEmpty(vcode)){
            log.error("verificationCode is expired , please try again！email:{}", registerRequest.getEmail());
            return BaseResponse.error("verificationCode is expired！, please try again！ to get it", ResultCode.PARAM_ERROR);
        }
        if(!vcode.equals(registerRequest.getVerificationCode())){
            log.error("verificationCode is wrong！vcode:{},registerRequest.getVerificationCode():{}", vcode, registerRequest.getVerificationCode());
            return BaseResponse.error("verificationCode is wrong！", ResultCode.PARAM_ERROR);
        }
        BaseResponse result = userService.ctRegister(registerRequest);
        if(result.getCode()==200){
            registerTokenCache.invalidate(registerRequest.getEmail());
        }
        return result;
    }

    @PostMapping("/login")
    @ResponseBody
    public BaseResponse login(@RequestBody LoginRequest loginRequest){
        log.info("login:{}", loginRequest);
        return userService.login(loginRequest);
    }

    @PostMapping("/ctLogin")
    @ResponseBody
    public BaseResponse ctLogin(@RequestBody LoginRequest loginRequest){
        log.info("ctLogin:{}", loginRequest);
        if(StringUtils.isEmpty(loginRequest.getUsername()) || StringUtils.isEmpty(loginRequest.getPassword())){
            return BaseResponse.error("用户名或密码不能为空！", ResultCode.PARAM_ERROR);
        }
        return userService.ctLogin(loginRequest);
    }

    @PostMapping("/logout")
    @ResponseBody
    public BaseResponse logout(HttpServletRequest request){
        log.info("logout ===>");
        String token = request.getHeader("token");
        Map tokenPayload = JwtUtils.getPayload(token);
        String tenantId = (String) tokenPayload.get("tenantId");
        if(StringUtils.isEmpty(tenantId)){
            log.error("logout tenantId is null,spaceInfoId:{}", tenantId);
            return BaseResponse.error("token异常", ResultCode.PARAM_ERROR);
        }
        return userService.logout(token);
    }

    @PostMapping("/login/apple")
    @ApiOperation(value = "苹果AppleID登录", produces = "application/json", consumes = "application/json")
    public BaseResponse appleIdLogin(@RequestBody UserSocialParam param) {
        if (param == null || StringUtils.isEmpty(param.getOpenId()) || StringUtils.isEmpty(param.getIdentityToken())) {
            return BaseResponse.error("openId/identityToken不能为空！", ResultCode.PARAM_ERROR);
        }
        boolean appleValid = appleIdValidService.isValid(param.getIdentityToken());
        if (appleValid) {
            // 校验通过，省略其他逻辑
        }
        return BaseResponse.ok();
    }



    @GetMapping("/getRegisterVcode")
    @ResponseBody
    public BaseResponse getRegisterVcode(@RequestParam("email") String email){
        log.info("getRegisterVcode email :{}", email);
        if(StringUtils.isEmpty(email)){
            return BaseResponse.error("邮箱地址不能为空！", ResultCode.PARAM_ERROR);
        }
        SaasUserInfo saasUserInfo = userService.getUserByUsername(email);
        if(saasUserInfo !=null){
            log.error("该邮箱已注册！email:{}", email);
            return BaseResponse.error("该邮箱已注册！", ResultCode.PARAM_ERROR);
        }
        // 从缓存中获取令牌
        String cachedToken = registerTokenCache.getIfPresent(email);
        if (cachedToken != null) {
            log.warn("getRegisterVcode is exist, email:{}", email);
            // 令牌已存在，直接返回成功
            return BaseResponse.error("验证码已发送，请查看邮箱", ResultCode.PARAM_ERROR);
        }

        // 发送重置链接到用户邮箱
        try {
            int randomNumber = ThreadLocalRandom.current().nextInt(0, 1000000);
            String verifyCode = String.format("%06d", randomNumber);
            EmailSender163.getInstance().sendEmail(email, "Register Mail",
                    "your register register Verification code : " + verifyCode);
            // 将令牌存储到缓存中，key为email
            registerTokenCache.put(email, verifyCode);
            log.info("getRegisterVcode email :{}, verifyCode:{}", email, verifyCode);
        } catch (Exception e) {
            log.error("Failed to send email.", e);
            return BaseResponse.error(ErrorCodeEnum.SYSTEM_ERROR.getCode(),"Failed to send email.");
        }
        return BaseResponse.ok();
    }

    @PostMapping("/logoff")
    @ResponseBody
    public BaseResponse logoff(HttpServletRequest request, @RequestBody LogoffRequest logoffRequest){
        log.info("logoff logoffRequest:{}", logoffRequest);
        if(StringUtils.isEmpty(logoffRequest.getUsername()) || StringUtils.isEmpty(logoffRequest.getPassword())){
            return BaseResponse.error("用户名或密码不能为空！", ResultCode.PARAM_ERROR);
        }
        String token = request.getHeader("token");
        String tenantId = JwtUtils.getTenantId(token);
        if(com.baomidou.mybatisplus.core.toolkit.StringUtils.isBlank(tenantId)){
            log.error("logoff tenantId is null, logoffRequest:{}", logoffRequest);
            return BaseResponse.error("token异常", ResultCode.PARAM_ERROR);
        }
        return userService.logoff(logoffRequest, token);
    }

    @GetMapping("/user/list")
    public BaseResponse list(HttpServletRequest request){
        String token = request.getHeader("token");
        List<String> roles = JwtUtils.getRole(token);
        if(!roles.contains(Constants.TENANT_ADMIN)){
            log.error("list , user has not permission");
            return BaseResponse.error("权限不足", ResultCode.PARAM_ERROR);
        }
        return BaseResponse.ok(userService.list(JwtUtils.getTenantId( token)));
    }

    @GetMapping("/user/detail")
    public BaseResponse detail(HttpServletRequest request, @RequestParam("id") Long id){
        String token = request.getHeader("token");
        List<String> roles = JwtUtils.getRole(token);
        if(!roles.contains(Constants.TENANT_ADMIN)){
            log.error("detail , user has not permission");
            return BaseResponse.error("权限不足", ResultCode.PARAM_ERROR);
        }
        SaasUserInfo saasUserInfo = userService.getUserById(id);
        if(saasUserInfo == null){
            log.error("detail , user is not exist, id:{}", id);
            return BaseResponse.error("用户不存在", ResultCode.PARAM_ERROR);
        }
        UserDetails userDetails = new UserDetails();
        BeanUtils.copyProperties(saasUserInfo, userDetails);
        List<SpaceInfo> spaces =  userService.getUserSpaces(id);
        userDetails.setSpaces( spaces);
        return BaseResponse.ok(userDetails);
    }

    @PostMapping("/user/space")
    @ResponseBody
    public BaseResponse space(HttpServletRequest request, @RequestBody UserSpaceRequest spaceRequest){
        String token = request.getHeader("token");
        List<String> roles = JwtUtils.getRole(token);
        if(!roles.contains(Constants.TENANT_ADMIN)){
            log.error("space , user has not permission");
            return BaseResponse.error("权限不足", ResultCode.PARAM_ERROR);
        }
        SaasSpaceInfo space = spaceService.getSpaceById(spaceRequest.getSpaceId());
        if(space == null){
            log.error("space , space is not exist, spaceId:{}", spaceRequest.getSpaceId());
            return BaseResponse.error("空间不存在", ResultCode.PARAM_ERROR);
        }
        String tenantId = JwtUtils.getTenantId(token);
        if(!space.getTenantId().equals(tenantId)){
            log.error("space , space is not belong to this tenant, spaceId:{}", spaceRequest.getSpaceId());
            return BaseResponse.error("非法空间", ResultCode.PARAM_ERROR);
        }
        SaasUserInfo user = userService.getUserById(spaceRequest.getUserId());
        if(user == null){
            log.error("space , user is not exist, userId:{}", spaceRequest.getUserId());
            return BaseResponse.error("用户不存在", ResultCode.PARAM_ERROR);
        }
        if(!user.getTenantId().equals(tenantId)){
            log.error("space , user is not belong to this tenant, userId:{}", spaceRequest.getUserId());
            return BaseResponse.error("非法用户", ResultCode.PARAM_ERROR);
        }
        return BaseResponse.ok(userService.space(spaceRequest));
    }

    @GetMapping("/user/stop")
    public BaseResponse stop(HttpServletRequest request, @RequestParam("id") Long id){
        String token = request.getHeader("token");
        List<String> roles = JwtUtils.getRole(token);
        if(!roles.contains(Constants.TENANT_ADMIN)){
            log.error("stop , user has not permission");
            return BaseResponse.error("权限不足", ResultCode.PARAM_ERROR);
        }
        SaasUserInfo user = userService.getUserById(id);
        if(user == null){
            log.error("stop , user is not exist, userId:{}", id);
            return BaseResponse.error("用户不存在", ResultCode.PARAM_ERROR);
        }
        String tenantId = JwtUtils.getTenantId(token);
        if(!user.getTenantId().equals(tenantId)){
            log.error("stop , user is not belong to this tenant, userId:{}", id);
            return BaseResponse.error("非法用户", ResultCode.PARAM_ERROR);
        }
        return BaseResponse.ok(userService.stop(id));
    }
}

